﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using BADDGUI.Utils;

namespace BADDGUI.Controls
{
	[Description("DataGridView that Saves Column Order, Width and Visibility to user.config")]
	[ToolboxBitmap(typeof(System.Windows.Forms.DataGridView))]
	public class BLCDataGridView : DataGridView
	{
        public BLCDataGridView(BLCForm Owner)
        {
            this.Owner = Owner;
        }

        private BLCForm _Owner;
        public BLCForm Owner
        {
            get { return _Owner; }
            set { _Owner = value; }
        }

        private List<DataGridViewColumn> _DisplayColumns = new List<DataGridViewColumn>();
        public List<DataGridViewColumn> DisplayColumns
        {
            get { return _DisplayColumns; }
            set { _DisplayColumns = value; }
        }

		public void SetColumnOrder()
		{
            this.DisplayColumns.Clear();

			if (!gfDataGridViewSetting.Default.ColumnOrder.ContainsKey(this.Name)) return;
			List<ColumnOrderItem> columnOrder = gfDataGridViewSetting.Default.ColumnOrder[this.Name];

			if (columnOrder != null)
			{
				var sorted = columnOrder.OrderBy(i => i.DisplayIndex);
				foreach (var item in sorted)
				{
					this.Columns[item.ColumnIndex].DisplayIndex = item.DisplayIndex;
					this.Columns[item.ColumnIndex].Visible = item.Visible;
					this.Columns[item.ColumnIndex].Width = item.Width;
                    this.Columns[item.ColumnIndex].SortMode = DataGridViewColumnSortMode.Automatic;
                    if (item.IsSortedColumn)
                    {
                        ListSortDirection SortDirection;
                        switch (item.SortOrder)
                        {
                            case SortOrder.Ascending:
                                SortDirection = ListSortDirection.Ascending;
                                break;
                            default:
                                SortDirection = ListSortDirection.Descending;
                                break;
                        }
                        this.Sort(this.Columns[item.ColumnIndex],SortDirection);
                    }

                    if (item.Visible) this.DisplayColumns.Add(this.Columns[item.ColumnIndex]);
				}
			}
		}
		
		public void SaveColumnOrder()
		{
			if (this.AllowUserToOrderColumns)
			{
				List<ColumnOrderItem> columnOrder = new List<ColumnOrderItem>();
				DataGridViewColumnCollection columns = this.Columns;
				for (int i = 0; i < columns.Count; i++)
				{
					columnOrder.Add(new ColumnOrderItem
					{
						ColumnIndex = i,
						DisplayIndex = columns[i].DisplayIndex,
						Visible = columns[i].Visible,
						Width = columns[i].Width,
                        IsSortedColumn = (this.SortedColumn == columns[i]),
                        SortOrder = this.SortedColumn == columns[i] ? this.SortOrder : SortOrder.None
					});
				}

				gfDataGridViewSetting.Default.ColumnOrder[this.Name] = columnOrder;
				gfDataGridViewSetting.Default.Save();
			}
		}

		protected override void OnCreateControl()
		{
			base.OnCreateControl();
            InitializeComponent();
            this.Name = "dgv" + this.Owner.Name.Right(4);
			//SetColumnOrder();
		}

        public void SetDisplayColumns()
        {
            DataGridViewColumn dgvCurCol = this.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
            if (dgvCurCol != null)
            {
                _DisplayColumns = new List<DataGridViewColumn>();

                _DisplayColumns.Add(dgvCurCol);
                DataGridViewColumn myCol;
                do
                {
                    myCol = this.Columns.GetNextColumn(dgvCurCol, DataGridViewElementStates.Visible, 
                                                                  DataGridViewElementStates.None);
                    if (myCol != null) _DisplayColumns.Add(myCol);
                    dgvCurCol = myCol;
                } while (myCol != null);
            }
        }

		protected override void Dispose(bool disposing)
		{
			SaveColumnOrder();
			base.Dispose(disposing);
		}

        private void InitializeComponent()
        {
            System.Windows.Forms.DataGridViewCellStyle ColumnHeaderStyle = new System.Windows.Forms.DataGridViewCellStyle();
            System.Windows.Forms.DataGridViewCellStyle CellStyle = new System.Windows.Forms.DataGridViewCellStyle();
            ((System.ComponentModel.ISupportInitialize)(this)).BeginInit();
            this.SuspendLayout();
            
            this.AllowUserToAddRows = false;
            this.AllowUserToDeleteRows = false;
            this.AllowUserToOrderColumns = true;
            this.AllowUserToResizeRows = false;
            this.AutoGenerateColumns = false;
            this.ShowCellErrors = false;
            this.ShowCellToolTips = false;
            this.ShowEditingIcon = false;
            this.ShowRowErrors = false;
            this.MultiSelect = false;
            this.ReadOnly = true;
            this.StandardTab = true;

            this.BackgroundColor = System.Drawing.SystemColors.Window;
            this.BorderStyle = System.Windows.Forms.BorderStyle.None;
            this.CellBorderStyle = DataGridViewCellBorderStyle.None;
            this.ColumnHeadersBorderStyle = System.Windows.Forms.DataGridViewHeaderBorderStyle.Single;
            this.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.DisableResizing;
            this.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
            this.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing;

            ColumnHeaderStyle.Alignment = DataGridViewContentAlignment.MiddleLeft;
            ColumnHeaderStyle.BackColor = SystemColors.Control;
            ColumnHeaderStyle.Font = new Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            ColumnHeaderStyle.ForeColor = SystemColors.WindowText;
            ColumnHeaderStyle.SelectionBackColor = SystemColors.Highlight;
            ColumnHeaderStyle.SelectionForeColor = SystemColors.HighlightText;
            ColumnHeaderStyle.WrapMode = DataGridViewTriState.True;
            this.ColumnHeadersDefaultCellStyle = ColumnHeaderStyle;

            CellStyle.Alignment = DataGridViewContentAlignment.MiddleLeft;
            CellStyle.BackColor = SystemColors.Window;
            CellStyle.Font = new Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            CellStyle.ForeColor = SystemColors.ControlText;
            CellStyle.SelectionBackColor = SystemColors.Highlight;
            CellStyle.SelectionForeColor = SystemColors.HighlightText;
            CellStyle.WrapMode = DataGridViewTriState.False;
            this.DefaultCellStyle = CellStyle;

            this.Dock = System.Windows.Forms.DockStyle.Fill;
            this.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically;
            this.GridColor = System.Drawing.SystemColors.Window;
            this.Location = new System.Drawing.Point(1, 0);
            
            this.ColumnHeadersHeight = 28;
            this.RowHeadersWidth = 25;
            this.RowTemplate.Height = 25;
            this.Size = new Size(805, 376);
            this.RowTemplate.Height = 22;

            ((System.ComponentModel.ISupportInitialize)(this)).EndInit();
            this.ResumeLayout(false);
        }
	}
	//-------------------------------------------------------------------------
	internal sealed class gfDataGridViewSetting : ApplicationSettingsBase
	{
		private static gfDataGridViewSetting _defaultInstace =
			(gfDataGridViewSetting)ApplicationSettingsBase
			.Synchronized(new gfDataGridViewSetting());
		//---------------------------------------------------------------------
		public static gfDataGridViewSetting Default
		{
			get { return _defaultInstace; }
		}
		//---------------------------------------------------------------------
		// Because there can be more than one DGV in the user-application
		// a dictionary is used to save the settings for this DGV.
		// As key the name of the control is used.
		[UserScopedSetting]
		[SettingsSerializeAs(SettingsSerializeAs.Binary)]
		[DefaultSettingValue("")]
		public Dictionary<string, List<ColumnOrderItem>> ColumnOrder
		{
			get { return this["ColumnOrder"] as Dictionary<string, List<ColumnOrderItem>>; }
			set { this["ColumnOrder"] = value; }
		}
	}
	//-------------------------------------------------------------------------
	[Serializable]
	public sealed class ColumnOrderItem
	{
		public int DisplayIndex { get; set; }
		public int Width { get; set; }
		public bool Visible { get; set; }
		public int ColumnIndex { get; set; }
        public bool IsSortedColumn { get; set; }
        public SortOrder SortOrder { get; set; }
	}
}